/*********************************************************************************************************************
 * COPYRIGHT NOTICE
 * Copyright (c) 2020,逐飞科技
 * All rights reserved.
 * 技术讨论QQ群：一群：179029047(已满)  二群：244861897(已满)  三群：824575535
 *
 * 以下所有内容版权均属逐飞科技所有，未经允许不得用于商业用途，
 * 欢迎各位使用并传播本程序，修改内容时必须保留逐飞科技的版权声明。
 *
 * @file       		pit_timer
 * @company	   		成都逐飞科技有限公司
 * @author     		逐飞科技(QQ790875685)
 * @version    		查看doc内version文件 版本说明
 * @Software 		MDK FOR C251 V5.60
 * @Target core		STC32G12K128
 * @Taobao   		https://seekfree.taobao.com/
 * @date       		2024-01-22
 ********************************************************************************************************************/
#include "zf_pwm.h"
#include "zf_gpio.h"
#include "zf_delay.h"
#include "zf_exti.h"
#include "zf_tim.h"
#include "comparator.h"
#include "bldc_config.h"
#include "pwm.h"
#include "battery.h"
#include "motor.h"
#include "board.h"

motor_struct motor;
uint8 timer4_isr_flag;

//-------------------------------------------------------------------------------------------------------------------
//  @brief      电机step加一
//  @param      void
//  @return
//  @since      v1.0
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void motor_next_step(void)
{
    motor.step++;
    while(6 <= motor.step)
    {
        motor.step -= 6;
    }
}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      电机换相函数
//  @param      void
//  @return
//  @since      v1.0
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void motor_commutation(void)
{
    switch(motor.step)
    {
		case 0:
		{
			pwm_a_bn_output();
			if(MOTOR_CLOSE_LOOP == motor.run_flag)
			{
				comparator_falling();
			}
		}
		break;
		case 1:
		{
			pwm_a_cn_output();
			if(MOTOR_CLOSE_LOOP == motor.run_flag)
			{
				comparator_rising();
			}
		}
		break;
		case 2:
		{
			pwm_b_cn_output();
			if(MOTOR_CLOSE_LOOP == motor.run_flag)
			{
				comparator_falling();
			}
		}
		break;
		case 3:
		{
			pwm_b_an_output();
			if(MOTOR_CLOSE_LOOP == motor.run_flag)
			{
				comparator_rising();
			}
		}
		break;
		case 4:
		{
			pwm_c_an_output();
			if(MOTOR_CLOSE_LOOP == motor.run_flag)
			{
				comparator_falling();
			}
		}
		break;
		case 5:
		{
			pwm_c_bn_output();
			if(MOTOR_CLOSE_LOOP == motor.run_flag)
			{
				comparator_rising();
			}
		}
		break;
		default:
			break;
    }
}


//-------------------------------------------------------------------------------------------------------------------
//  @brief      定时器4重新配置
//  @param      void
//  @return     uint16          返回当前计时器的时间
//  @since      v1.0
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
uint16 tim4_reconfig(void)
{
    uint16 temp;
    // 获取换相时间
    T4T3M &= ~0x80; // 停止定时器
    temp = T4H;
    temp = (temp << 8) | T4L;
    T4L = 0;
    T4H = 0;
    T4T3M |= 0x80;  // 开启定时器
    return temp;
}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      定时器4中断函数
//  @param      void
//  @return     void
//  @since      v1.0
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void TM4_Isr(void) interrupt 20
{
    TIM4_CLEAR_FLAG;
    // 换相超时
    timer4_isr_flag = 1;
    if(MOTOR_CLOSE_LOOP == motor.run_flag && (30 * 7) < motor.commutation_num)
    {
        // 正在运行的时候 进入此中断应该立即关闭输出
        motor.run_flag = MOTOR_STOP_STALL;
    }
}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      比较器中断函数
//  @param      void
//  @return     void
//  @since      v1.0
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void comparator_isr(void) interrupt 21		// 比较器中断函数, 检测到反电动势过0事件
{
    // 获取换相时间
    uint16 temp = (T4H << 8) | T4L;
    CMPCR1 &= ~0x40;	// 需软件清除中断标志位
	
// 去除反电动势毛刺
//    if((temp < (motor.commutation_time_sum / 24) && (30 * 7) < motor.commutation_num))
//    {
//        return;
//    }
	
    if(MOTOR_CLOSE_LOOP == motor.run_flag)
    {
        // 清空计数器
        T4T3M &= ~0x80; // 停止定时器
        T4L = 0;
        T4H = 0;
        T4T3M |= 0x80;  // 开启定时器
        // 去掉最早的数据
        motor.commutation_time_sum -= motor.commutation_time[motor.step];
        // 保存换相时间
        motor.commutation_time[motor.step] = temp;
        // 叠加新的换相时间，求6次换相总时长
        motor.commutation_time_sum += temp;
        motor.commutation_num++;
        // 本次换向60度的时间，在上一次换向一圈时间的40度到80度，否则认为换向错误
        if((temp > ((motor.commutation_time_sum / (360.0f / 40)))) && (temp < (motor.commutation_time_sum / (360.0f / 80))))
        {
            // 延时减去换向失败计数器
            if((motor.commutation_failed_num))
            {
                motor.commutation_failed_num--;
            }
            // 缓慢加减速
            if(motor.duty != motor.duty_register)
            {
                if(0 == (motor.commutation_num%2) && (motor.duty_register != motor.duty))
                {
                    if(motor.duty > motor.duty_register)
                    {
                        motor.duty_register ++;
                        if(BLDC_MAX_DUTY < motor.duty_register)
                        {
                            motor.duty_register = BLDC_MAX_DUTY;
                        }
                    }
                    else
                    {
                        motor.duty_register = motor.duty;
                    }
                    pwm_center_duty_update(motor.duty_register);
                }
            }
        }
        else
        {
            if(BLDC_COMMUTATION_FAILED_MAX < motor.commutation_failed_num++)
            {
                motor_stop();
                motor.run_flag = MOTOR_STOP_STALL;
            }
        }
        // 修改PWM占空比

        motor_next_step();
        motor_commutation();
    }
}


#define MUSIC_DELAY_MS   250
//-------------------------------------------------------------------------------------------------------------------
//  @brief      电机上电鸣叫
//  @param      volume          鸣叫音量大小
//  @return     void
//  @since      v1.0
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void motor_power_on_beep(uint16 volume)
{
	uint16  frequency_spectrum[6] = {0, 523, 587, 659, 698, 783};
    uint16 beep_duty;
    beep_duty = volume;
    // 保护限制，避免设置过大烧毁电机
    if(100 < beep_duty)
    {
        beep_duty = 100;
    }
	
	// A上桥PWM B下桥常开
    PWM_A_H_PIN = 0;
    PWM_A_L_PIN = 0;
    PWM_B_H_PIN = 0;
    PWM_B_L_PIN = 1;
    PWM_C_H_PIN = 0;
    PWM_C_L_PIN = 0;
	pwm_a_bn_output();
	pwm_center_duty_update(motor.duty_register);
	pwm_init(PWMA_CH1P_P20, frequency_spectrum[1], beep_duty);
	PWMA_ENO = 1<<0;
	delay_ms(MUSIC_DELAY_MS);
	
	// B上桥PWM C下桥常开
	PWM_A_H_PIN = 0;
    PWM_A_L_PIN = 0;
    PWM_B_H_PIN = 0;
    PWM_B_L_PIN = 0;
    PWM_C_H_PIN = 0;
    PWM_C_L_PIN = 1;
	pwm_init(PWMA_CH2P_P22, frequency_spectrum[2], beep_duty);
	PWMA_ENO = 1<<2;
	delay_ms(MUSIC_DELAY_MS);
	
	// C上桥PWM A下桥常开
	PWM_A_H_PIN = 0;
    PWM_A_L_PIN = 1;
    PWM_B_H_PIN = 0;
    PWM_B_L_PIN = 0;
    PWM_C_H_PIN = 0;
    PWM_C_L_PIN = 0;
	pwm_init(PWMA_CH3P_P24, frequency_spectrum[3], beep_duty);
	PWMA_ENO = 1<<4;
	delay_ms(MUSIC_DELAY_MS);
	
}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      电机停止
//  @param      void
//  @return     void
//  @since      v1.0
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void motor_stop(void)
{
    pwm_center_duty_update(0);
    pwm_brake();
    comparator_close_isr();
}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      电机初始化
//  @param      void
//  @return     void
//  @since      v1.0
//  Sample usage:
//-------------------------------------------------------------------------------------------------------------------
void motor_init(void)
{
    // 变量清零
    motor.duty = 0;
    motor.duty_register = 0;
    motor.run_flag = 0;
    motor.motor_start_delay = 0;
    motor.motor_start_wait = 0;
    motor.restart_delay = 0;
    motor.commutation_time_sum = 0;
    motor.commutation_num = 0;
	
    T4T3M = 1<<7;	// 定时器4使能
    T4T3M |= 1<<5;	// T4 1T模式
    T4T3M |= 1<<3;	// 定时器3使能
    T4T3M |= 1<<1;	// T3 1T模式
    T3L = 0;
    T3H = 0;
    TM3PS = (sys_clk / 1000000) - 1;	// 设置分频系数，时基为1us
    T4L = 0;
    T4H = 0;
    TM4PS = (sys_clk / 1000000) - 1;	// 设置分频系数，时基为1us

    IP = 0;
    IPH = 0;
    IP2 = 0;
    IP2H = 0;
    // 设置比较器与PWM的中断为最高优先级
    IP |= 1<<7;
    IPH |= 1<<7;
    IP2 |= 1<<5;
    IP2H |= 1<<5;
#if (1 == BLDC_BEEP_ENABLE)
    // 电机鸣叫表示初始化完成
    motor_power_on_beep(BLDC_BEEP_VOLUME);
#endif
}